import typing
from enum import Enum

from fastapi import APIRouter
from pydantic import BaseModel

from DataModels.database import User
from DataModels.share import RespResultCode, RespInfo, StatusInfo, TokenPayload
from config import logger
from utils.share import timestamp
from utils.token import decode_token, generate_token


class LoginType(Enum):
    Phone = 2
    Password = 1


class LoginRequest(BaseModel):
    type: LoginType
    code: str
    phone: typing.Optional[str] = None


# response =>
# {token: str}


login_router = APIRouter(prefix="/login")


@login_router.post("", response_model=RespInfo)
async def login(data: LoginRequest):
    login_type = data.type
    if login_type == LoginType.Password:
        phone = data.phone
        pwd = data.code

        user = await User.find_one(User.phone == phone)
        if not user:
            return RespInfo(
                status=StatusInfo(
                    code=RespResultCode.PhoneNotFound,
                    msg="用户不存在",
                )
            )

        if user.password != pwd:
            return RespInfo(
                status=StatusInfo(
                    code=RespResultCode.CodeErr,
                    msg="密码错误",
                )
            )

        return RespInfo(
            token=generate_token(
                TokenPayload(phone=str(phone), createTime=timestamp())
            ),
            status=StatusInfo(
                code=RespResultCode.Success,
                msg="登录成功",
            ),
        )
    elif login_type == LoginType.Phone:
        try:
            token = decode_token(data.code)
        except Exception as e:
            logger.error(e)
            return RespInfo(
                status=StatusInfo(
                    code=RespResultCode.DataCorrupted,
                    msg="用户凭据无效",
                )
            )
        phone = token.phone

        user = await User.find_one(User.phone == phone)
        if not user:
            return RespInfo(
                status=StatusInfo(
                    code=RespResultCode.PhoneNotFound,
                    msg="用户不存在",
                )
            )
        return RespInfo(
            token=generate_token(TokenPayload(phone=phone, createTime=timestamp())),  # type: ignore
            status=StatusInfo(
                code=RespResultCode.Success,
                msg="登录成功",
            ),
        )

    else:
        return RespInfo(
            status=StatusInfo(
                code=RespResultCode.UnkownLoginType,
                msg="未知登录类型",
            )
        )
